home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / news / readers / nn / nn6.4.patch16 < prev    next >
Encoding:
Text File  |  1991-04-18  |  48.1 KB  |  1,755 lines

  1.          This is an official patch to nn release 6.4
  2.          -------------------------------------------
  3.  
  4.                   PATCH #16
  5.  
  6.                 Priority: HIGH
  7.  
  8.  
  9. Adding consolidated menus in patch #15 involved quite significant
  10. changes to central parts of the menu handling logic, so some bugs were
  11. to expected.  But it caused more serious bugs than I would have tought
  12. possible given that I had tested it to various degrees on three
  13. different platforms.  Most significantly was a bug that caused a core
  14. dump when the last article in the group was touched - even when
  15. consolidated menus were not used.
  16.  
  17. There were also a stupid bug in the way range selections were handled
  18. which would cause it to select too few or completely wrong ranges of
  19. articles.
  20.  
  21. There would be problems handling the case where no sorting is
  22. performed on the articles to be presented on the menu - specifically
  23. in the online manual, but also if `fsort' or `sort' were not set when
  24. entering a folder or a group.
  25.  
  26. A nasty bug in the "nnmaster -k" logic has been found (not related to
  27. patch #15), where nnmaster may potentially send a SIGTERM to process 1
  28. (init) if nnmaster is found to be running on another host.  Usually,
  29. this wouldn't cause problems since nnmaster is not supposed to run as
  30. root, but you never know...
  31.  
  32. Some other problems not related to patch #15 are also fixed by this
  33. patch:
  34.  
  35. - Nn will now offer to use a .newsrc.bak fil if .newsrc is missing or empty.
  36.  
  37. - Problems with nnadmin D)ata and V)alidate incorrectly reporting corruption
  38.   for empty groups have been fixed.
  39.  
  40. - Reply in :rmail no longer makes an "In /usr/mail/.... you write" line.
  41.  
  42. - Superfluous "Distribution: world" header lines are eliminated.
  43.  
  44.  
  45. A few additions has also been made in this patch:
  46.  
  47. I have received some complaints about the layout of the consolidated
  48. menu - it is too messy, especially since the subjects are not aligned.
  49. It is hard to do this perfectly, but there is a new variable
  50. `counter-padding' which can be set to a minimum padding of all
  51. subjects to start approximately at the same column (default is 5).
  52.  
  53. There is also a new boolean variable `consolidated-manual' which can
  54. be set to present the online manual with a "one line per program"
  55. selection menu.  (default off).  To make use of this feature, the dumb
  56. "Name" entry on the online manual has been changed to show the
  57. contents of the NAME section, i.e. the purpose of the program.
  58.  
  59. Hooks to allow mail aliases to be expanded are now now provided
  60. through the `mail-alias-expander' variable.  To use this feature,
  61. programs must be written to actually expand the aliases.  Such
  62. programs may be included in future patches as they become available.
  63.  
  64.  
  65. As usual, all changes are described in the updated RELEASE_NOTES file
  66. (read that for more details about this patch).  Thanks to all who
  67. reported bugs and provided fixes.
  68.  
  69. To apply this patch, use nn's :patch command, or run this command from
  70. the shell in the root of the nn source tree:
  71.     patch -p0 < this-article
  72.  
  73. Then run "make all" and "./inst u".
  74.  
  75. ++Kim Storm
  76.  
  77. ===================================================================
  78.  
  79. *** ./LAST/admin.c    Fri Apr 12 19:28:20 1991
  80. --- admin.c    Tue Apr 16 19:57:52 1991
  81. ***************
  82. *** 274,282 ****
  83.   
  84.       if (verbose) { printf("\r%s: ", gh->group_name); clrline(); }
  85.   
  86. !     if (init_group(gh) <= 0) {
  87. !       if (verbose)
  88. !     printf("NO DIRECTORY (ok)");
  89.       return 1; /* no directory/ignored */
  90.       }
  91.   
  92. --- 274,282 ----
  93.   
  94.       if (verbose) { printf("\r%s: ", gh->group_name); clrline(); }
  95.   
  96. !     /* init_group returns ok for gh == current_group before check on NO_DIR */
  97. !     if ((gh->master_flag & M_NO_DIRECTORY) || init_group(gh) <= 0) {
  98. !     if (verbose) printf("NO DIRECTORY (ok)");
  99.       return 1; /* no directory/ignored */
  100.       }
  101.   
  102. ***************
  103. *** 433,438 ****
  104. --- 433,443 ----
  105.   
  106.       update_group(gh);
  107.   
  108. +     if (gh->index_write_offset == 0) {
  109. +     printf("group %s is empty\n", gh->group_name);
  110. +     return 1;
  111. +     }
  112. +     
  113.       first_article = get_entry("First article",
  114.                     (long)gh->first_db_article,
  115.                     (long)gh->last_db_article);
  116. *** ./LAST/answer.c    Fri Apr 12 19:28:21 1991
  117. --- answer.c    Thu Apr 18 10:27:24 1991
  118. ***************
  119. *** 33,38 ****
  120. --- 33,39 ----
  121.   export int  inews_pipe_input    = 1;
  122.   export char *editor_program    = NULL;
  123.   export char *spell_checker    = NULL;
  124. + export char *mail_alias_expander = NULL;
  125.   
  126.   export char *bug_address    = BUG_REPORT_ADDRESS;
  127.   
  128. ***************
  129. *** 363,368 ****
  130. --- 364,370 ----
  131.       if (editor_program != NULL)
  132.           aux_param_str(param, "EDITOR", editor_program);
  133.       aux_param_str(param, "SPELL_CHECKER", spell_checker);
  134. +     aux_param_str(param, "ALIAS_EXPANDER", mail_alias_expander);
  135.       aux_param_str(param, "PAGER", pager);
  136.       aux_param_str(param, "MAILER", mailer_program);
  137.       aux_param_bool(param, "MAILER_PIPE", mailer_pipe_input);
  138. ***************
  139. *** 578,584 ****
  140.       end_header(t, extra_mail_headers);
  141.   
  142.       if (incl) {
  143. !         fprintf(t, "In %s you write:\n", current_group->group_name);
  144.           ed_line++;
  145.       }
  146.       }
  147. --- 580,589 ----
  148.       end_header(t, extra_mail_headers);
  149.   
  150.       if (incl) {
  151. !         if (current_group->group_flag & G_FOLDER)
  152. !         fprintf(t, "You write:\n");
  153. !         else
  154. !         fprintf(t, "In %s you write:\n", current_group->group_name);
  155.           ed_line++;
  156.       }
  157.       }
  158. ***************
  159. *** 622,629 ****
  160.   
  161.       str = get_distr(news.ng_dist, distribution_follow);
  162.       if (str == NULL) goto close_t;
  163. !     fprintf(t, "Distribution: %s\n", str);
  164. !     ed_line++;
  165.   
  166.       ref_line(t);
  167.   
  168. --- 627,636 ----
  169.   
  170.       str = get_distr(news.ng_dist, distribution_follow);
  171.       if (str == NULL) goto close_t;
  172. !     if (strcmp(str, "world")) {
  173. !         fprintf(t, "Distribution: %s\n", str);
  174. !         ed_line++;
  175. !     }
  176.   
  177.       ref_line(t);
  178.   
  179. ***************
  180. *** 861,867 ****
  181.       int ngroups, i;
  182.       char newsgroups[FILENAME*2];
  183.   
  184. !     init_term(1);
  185.       visit_init_file(0, (char *)NULL);
  186.       init_answer();
  187.       current_group = NULL;
  188. --- 868,874 ----
  189.       int ngroups, i;
  190.       char newsgroups[FILENAME*2];
  191.   
  192. !     init_term(0);
  193.       visit_init_file(0, (char *)NULL);
  194.       init_answer();
  195.       current_group = NULL;
  196. ***************
  197. *** 884,889 ****
  198. --- 891,905 ----
  199.       post_to_groups = newsgroups;
  200.       }
  201.   
  202. +     if (ngroups > 0 && post_no_edit && post_subject && post_distribution) {
  203. +     if (!post_summary) post_summary = "";
  204. +     if (!post_keywords) post_keywords = "";
  205. +     post_menu();
  206. +     goto no_dialogue;
  207. +     }
  208. +     
  209. +     init_term(1);
  210.       raw();
  211.       clrdisp();
  212.       prompt_line = 0;
  213. ***************
  214. *** 890,895 ****
  215. --- 906,913 ----
  216.       if (post_menu() == 2) clrdisp();
  217.       putchar(CR); putchar(NL);
  218.       unset_raw();
  219. +  no_dialogue:
  220.       if (*delayed_msg)
  221.       printf("%s\n", delayed_msg);
  222.   
  223. ***************
  224. *** 1006,1012 ****
  225.       if (!post_no_edit)
  226.       prompt("\1WAIT\1");
  227.   
  228. !     ed_line = 4;
  229.   #ifdef NNTP
  230.   #ifdef NNTP_MINI_INEWS_HEADER
  231.       mini_inews_header(t);
  232. --- 1024,1030 ----
  233.       if (!post_no_edit)
  234.       prompt("\1WAIT\1");
  235.   
  236. !     ed_line = 3;
  237.   #ifdef NNTP
  238.   #ifdef NNTP_MINI_INEWS_HEADER
  239.       mini_inews_header(t);
  240. ***************
  241. *** 1013,1019 ****
  242.   #endif
  243.   #endif
  244.       fprintf(t, "Newsgroups: %s\n", group_name);
  245. !     fprintf(t, "Distribution: %s\n", distribution);
  246.       fprintf(t, "Subject: %s\n", subject);
  247.       if (*summary) {
  248.       fprintf(t, "Summary: %s\n", summary);
  249. --- 1031,1040 ----
  250.   #endif
  251.   #endif
  252.       fprintf(t, "Newsgroups: %s\n", group_name);
  253. !     if (strcmp(distribution, "world")) {
  254. !     fprintf(t, "Distribution: %s\n", distribution);
  255. !     ed_line++;
  256. !     }
  257.       fprintf(t, "Subject: %s\n", subject);
  258.       if (*summary) {
  259.       fprintf(t, "Summary: %s\n", summary);
  260. *** ./LAST/articles.c    Tue Sep 18 12:44:50 1990
  261. --- articles.c    Tue Apr 16 21:15:11 1991
  262. ***************
  263. *** 328,334 ****
  264.               n = db_hdr.dh_cross_postings;
  265.               break;
  266.           }
  267. !         if (cpgh->group_flag & G_UNSUBSCRIBED) continue;
  268.   
  269.           if (!seq_cross_filtering) break;
  270.           if (cpgh->preseq_index > 0 &&
  271. --- 328,335 ----
  272.               n = db_hdr.dh_cross_postings;
  273.               break;
  274.           }
  275. !         if (!(flags & ACC_ALSO_UNSUB_GROUPS))
  276. !             if (cpgh->group_flag & G_UNSUBSCRIBED) continue;
  277.   
  278.           if (!seq_cross_filtering) break;
  279.           if (cpgh->preseq_index > 0 &&
  280. ***************
  281. *** 467,472 ****
  282. --- 468,475 ----
  283.   
  284.       if ((flags & ACC_DONT_SORT_ARTICLES) == 0)
  285.       sort_articles(-1);
  286. +     else
  287. +     no_sort_articles();
  288.   
  289.       return n_articles > 0 ? 1 : 0;
  290.   
  291. *** ./LAST/articles.h    Thu Jul 19 18:12:10 1990
  292. --- articles.h    Tue Apr 16 21:15:12 1991
  293. ***************
  294. *** 54,56 ****
  295. --- 54,57 ----
  296.   #define ACC_DO_KILL        FLAG(14) /* do auto-kill/select */
  297.   #define    ACC_PARSE_VARIABLES    FLAG(15) /* kill, split, etc. */
  298.   #define ACC_MERGED_NEWSRC    FLAG(16) /* merge orig and cur .newsrc */
  299. + #define ACC_ALSO_UNSUB_GROUPS    FLAG(17) /* kill x-posts based on unsub also */
  300. *** ./LAST/aux.sh    Wed Feb  6 19:14:12 1991
  301. --- aux.sh    Tue Apr 16 23:46:20 1991
  302. ***************
  303. *** 27,32 ****
  304. --- 27,33 ----
  305.   #    MAILER        [mailer]
  306.   #    MAILER_PIPE    [mailer-pipe-input]
  307.   #    DFLT_ANSW    [response-default-answer]
  308. + #    ALIAS_EXPANDER    [mail-alias-expander]
  309.   
  310.   CC=""
  311.   
  312. ***************
  313. *** 199,204 ****
  314. --- 200,206 ----
  315.       if [ -n "$COPY" ] ; then
  316.         rm -f $COPY
  317.       fi
  318. +     rm -f $WORK
  319.       exit 22 ;;
  320.       esac
  321.       ;;
  322. ***************
  323. *** 339,344 ****
  324. --- 341,349 ----
  325.     case "$OPERATION" in
  326.   
  327.       reply|forward|mail)
  328. +       if [ -n "${ALIAS_EXPANDER}" ] ; then
  329. +     ${ALIAS_EXPANDER} $FINAL
  330. +       fi
  331.         if ${MAILER_PIPE} ; then
  332.           $MAILER < $FINAL
  333.           x=$?
  334. *** ./LAST/doc/RELEASE_NOTES    Fri Apr 12 19:29:27 1991
  335. --- doc/RELEASE_NOTES    Thu Apr 18 10:50:44 1991
  336. ***************
  337. *** 1547,1553 ****
  338. --- 1547,1682 ----
  339.   From:    meulenbr@cst.philips.nl (Frans Meulenbroeks)
  340.   Fixed:    Patch #15 [menu.c]
  341.   
  342. + Prog:    nnmaster
  343. + Title:    -k option would kill process `1' if master is running on another host.
  344. + From:    Peter Wemm <peter@cutmcvax.cs.curtin.edu.au>
  345. + Fixed:    Patch #16 [master.c]
  346. + Prog:    nn
  347. + Title:    dumps core after selecting/previewing/junking last article in group
  348. + From:    Steven.Grimm@ebay.sun.com (Steven Grimm) +fix
  349. +     Toshinori Maeno <tmaeno@cc.titech.ac.jp> +fix
  350. +     eggert@twinsun.com (Paul Eggert) +fix
  351. +     ... and many more ...
  352. + Fixed:    Patch #16 [menu.c]
  353. + Prog:    nn
  354. + Title:    Selecting range a-d only selects articles a-c.
  355. + From:    Tom Ivar Helbekkmo <tih@barsoom.nhh.no>
  356. + Fixed:    Patch #16 [menu.c]
  357. + Prog:    nn
  358. + Title:    Selecting range c-l on *second* menu page only selects wrong articles.
  359. + From:    dean%coplex@relay.eu.net (Dean Brooks)
  360. + Fixed:    Patch #16 [menu.c]
  361. + Prog:    nn
  362. + Title:    :man command gives an empty menu if consolidated-menu is on.
  363. + From:    Bill Irwin <bill@twg.bc.ca>
  364. + Fixed:    Patch #16 [folder.c sort.c]
  365. + Prog:    nn
  366. + Title:    :man command dumps core when entry is selected when cons-menu is off.
  367. + From:    Bill Irwin <bill@twg.bc.ca>
  368. + Fixed:    Patch #16 [folder.c sort.c]
  369. + Prog:    nn
  370. + Title:    Reading folders with fsort=off or groups with sort=off fails horribly.
  371. + From:    KFS
  372. + Fixed:    Patch #16 [articles.c folder.c group.c sort.c]
  373. + Prog:    nn
  374. + Title:    Selecting a closed subject in slow_mode still redraw the whole line.
  375. + From:    david@wyvern.cs.uow.edu.au (David E A Wilson)
  376. + Prog:    nn
  377. + Title:    A long menu line for a closed subject will sometimes wrap to next line.
  378. + From:    david@wyvern.cs.uow.edu.au (David E A Wilson)
  379. + Fixed:    Patch #16 [menu.c]
  380. +     If found a "cookie" that wasn't counted - I hope that was it...
  381. + Prog:    nn
  382. + Title:    Subjects are not aligned on consolidated menus.
  383. + From:    mpp@uf.msc.umn.edu (Mike Pritchard)
  384. + Fixed:    Patch #16 [menu.c variable.c nn.1]
  385. +     There is a new variable counter-padding (=5) to control this.
  386. + Prog:    regression testing
  387. + Title:    The time stamps in scripts and #nn in version prevent regression tests.
  388. + From:    eggert@twinsun.com (Paul Eggert)
  389. + Fixed:    Patch #16 [prefix.c global.c]  (removed both)
  390. + Prog:    nn, nnpost
  391. + Title:    A "Distribution: world" line should be omitted from header.
  392. + From:    tale@cs.rpi.edu (David C Lawrence)
  393. + Fixed:    Patch #16 [answer.c]
  394. + Prog:    nn
  395. + Title:    :rmail reply says: In /usr/mail/spool/wb8foz/mbox, ...
  396. + From:    David Lesher <wb8foz@mthvax.cs.miami.edu>
  397. + Fixed:    Patch #16 [answer.c]
  398. + Prog:    nnadmin
  399. + Title:    Dumping D)ata in an empty group reports corrupted database.
  400. + From:    david@cs.uow.edu.au (David E A Wilson)
  401. + Fixed:    Patch #16 [admin.c]
  402. + Prog:    nnadmin
  403. + Title:    V)alidate in G)roup menu for group with NO_DIR would report errors.
  404. + From:    KFS
  405. + Fixed:    Patch #16 [admin.c]
  406.   
  407. + Prog:    nn
  408. + Title:    `unset fsort' doesn't work unless `set fsort' has been used.
  409. + From:     root@speech.kth.se (Roger Lindell)
  410. + Fixed:    Pacth #16 [variable.c]
  411. + Prog:    nn
  412. + Title:    Some systems use // in network file names, but they cannot be entered.
  413. + From:    itkin@guinan.transact.com (Steven List)
  414. + Fixed:    Patch #16 [term.c variable.c nn.1]
  415. +     There is a new `guard-double-slash' variable that can be set.
  416. + Prog:    nn, nngrab
  417. + Title:    nn -xXm would sometimes not eliminate cross-posted articles.
  418. + From:    eggert@twinsun.com (Paul Eggert)
  419. + Fixed:    Patch #16 [articles.c articles.h group.c sequence.c]
  420. + Prog:    nn
  421. + Title:    .newsrc.bak is removed if .newsrc doesn't exist (or is EMPTY).
  422. + From:    geoff@world.std.com <Geoff Collyer>
  423. + Fixed:    Patch #16 [newsrc.c]
  424. + Prog:    nn
  425. + Title:    h)old option did not remove temporary work file.
  426. + From:    KFS
  427. + Fixed:    Patch #16 [aux.sh]
  428. + Prog:    nn
  429. + Title:    G {goto-group} does not honour: nosplit, nosort, kill, a.o.
  430. + From:    jfsenior@unix1.tcd.ie (John Senior)
  431. + Fixed:    Patch #16 [group.c]
  432. + Prog:    nngrep
  433. + Title:    running nngrep without arguments may give memory allocation error.
  434. + From:    dean%coplex@relay.eu.net (Dean Brooks)
  435. + Fixed:    Patch #16 [newsrc.c]
  436. + Prog:    nncheck
  437. + Title:    nncheck -Q requires $TERM variable is set.
  438. + From:    allan@rind.cs.cornell.edu (James Allan)
  439. +     pt%geovision@uunet.UU.NET (Paul Tomblin)
  440. + Fixed:    Patch #16 [term.c]
  441. + Prog:    nnpost
  442. + Title:    nnpost requires $TERM variable also when no input is required.
  443. + From:    rock@warp.Eng.Sun.COM (Bill Petro)
  444. + Fixed:    Patch #16 [answer.c term.c]
  445.   New features since initial 6.4.0 release
  446.   ----------------------------------------
  447.   
  448. ***************
  449. *** 2087,2089 ****
  450. --- 2216,2246 ----
  451.   Title:    Blank lines can now be added between menu lines via `menu-spacing'.
  452.   From:    KFS on request from salsbury@acsu.buffalo.edu (Patrick G. Salsbury)
  453.   Added:    Patch #15 [menu.c variable.c nn.1]
  454. + Prog:    nn
  455. + Title:    The online manual can now be consolidated too (one program per line)
  456. + From:    KFS
  457. + Added:    Patch #16 [format.awk folder.c variable.c nn.1]
  458. +     There is a new boolean variable to set: consolidated-manual.
  459. + Prog:    nn, nngrab
  460. + Title:    The update intervals for the merge report in nngrab can now be changed.
  461. + From:    KFS
  462. + Added:    Patch #16 [variable.c nn.1]
  463. +     There is a new integer variable `merge-report-rate'.
  464. + Prog:    nn
  465. + Title:    Hooks are provided to allow mail aliases to be expanded.
  466. + From:    KFS on numerous requests.
  467. + Added:    Patch #16 [aux.sh answer.c variable.c nn.1]
  468. +     There is a new variable `mail-alias-expander' which may be set
  469. +     to a command which will expand aliases in the file given to it
  470. +     as its last argument.  No alias expanders are currently avaliable.
  471. + Prog:    nnpost
  472. + Title:    Simplified and documented unattended posting of articles.
  473. + From:    KFS
  474. + Added:    Patch #16 [answer.c nnpost.1]
  475. *** ./LAST/folder.c    Fri Apr 12 19:29:28 1991
  476. --- folder.c    Mon Apr 15 20:56:52 1991
  477. ***************
  478. *** 23,28 ****
  479. --- 23,29 ----
  480.   export char *backup_folder_path = "BackupFolder~";
  481.   export int  keep_backup_folder = 1;
  482.   export int  convert_folder_mode = 0; /* ignore folder's format on rewrite */
  483. + export int  consolidated_manual = 0;
  484.   
  485.   import int fmt_linenum;
  486.   import char *header_lines;
  487. ***************
  488. *** 409,416 ****
  489.       if (n_articles > 1) {
  490.           clrdisp();
  491.           prompt_line = 2;
  492. !         if (mode == 0 && !dont_sort_folders) sort_articles(-1);
  493. !     }
  494.   
  495.       cc_save = cancel_count;
  496.       cancel_count = 0;
  497. --- 410,434 ----
  498.       if (n_articles > 1) {
  499.           clrdisp();
  500.           prompt_line = 2;
  501. !         if (mode == 0 && !dont_sort_folders)
  502. !         sort_articles(-1);
  503. !         else if (mode == 1) {
  504. !         extern int bypass_consolidation;
  505. !         article_number n;
  506. !         for (n = 0; n < n_articles; n++) {
  507. !             ah = articles[n];
  508. !             if (n == 0)
  509. !             ah->flag |= A_ROOT_ART;
  510. !             else if (strcmp(ah->sender, articles[n-1]->sender) == 0)
  511. !             articles[n-1]->flag |= A_NEXT_SAME;
  512. !             else
  513. !             ah->flag |= A_ROOT_ART;
  514. !         }
  515. !         bypass_consolidation = consolidated_manual ? 2 : 1;
  516. !         } else
  517. !         no_sort_articles();
  518. !     } else
  519. !         no_sort_articles();
  520.   
  521.       cc_save = cancel_count;
  522.       cancel_count = 0;
  523. *** ./LAST/format.awk    Fri Apr 12 19:28:32 1991
  524. --- format.awk    Mon Apr 15 20:21:42 1991
  525. ***************
  526. *** 15,22 ****
  527.       firstsh = 0
  528.   
  529.       printf("From: %s\nSubject:", progname);
  530. !     for (i = 2; i <= NF; i++) printf(" %s", $i);
  531. !     printf("\n\n")
  532.   
  533.       linebuf = indent = ""
  534.       curcol = indcol = 0
  535. --- 15,29 ----
  536.       firstsh = 0
  537.   
  538.       printf("From: %s\nSubject:", progname);
  539. !     if ($2 == "NAME") {
  540. !         getline
  541. !         for (i = 2; i <= NF; i++) printf(" %s", $i);
  542. !         printf("\n\n")
  543. !         print
  544. !     } else {
  545. !         for (i = 2; i <= NF; i++) printf(" %s", $i);
  546. !         printf("\n\n")
  547. !     }
  548.   
  549.       linebuf = indent = ""
  550.       curcol = indcol = 0
  551. *** ./LAST/global.c    Wed Feb  6 19:14:17 1991
  552. --- global.c    Mon Apr 15 21:58:31 1991
  553. ***************
  554. *** 179,187 ****
  555. --- 179,191 ----
  556.       signal(SIGPWR, catch_hangup);
  557.   #endif
  558.   
  559. + #ifdef CONFIG_NUM_IN_VERSION
  560.       sprintf(version_id, "%s.%d #%d", RELEASE, PATCHLEVEL,
  561.   #include "update.h"
  562.           );
  563. + #else
  564. +     sprintf(version_id, "%s.%d", RELEASE, PATCHLEVEL);
  565. + #endif
  566.   
  567.       user_id = getuid();
  568.   
  569. *** ./LAST/group.c    Fri Apr 12 19:29:28 1991
  570. --- group.c    Wed Apr 17 09:21:14 1991
  571. ***************
  572. *** 326,332 ****
  573.       }
  574.   
  575.       if (mg_head != NULL) {
  576. !     if (!dont_sort_articles) sort_articles(-1);
  577.       init_group(mg_head);
  578.       }
  579.   
  580. --- 326,335 ----
  581.       }
  582.   
  583.       if (mg_head != NULL) {
  584. !     if (dont_sort_articles)
  585. !         no_sort_articles();
  586. !     else
  587. !         sort_articles(-1);
  588.       init_group(mg_head);
  589.       }
  590.   
  591. ***************
  592. *** 464,470 ****
  593.       read_mode_group = NULL;
  594.       
  595.       mask = NULL;
  596.       if (command == K_GOTO_GROUP)
  597.       goto get_group_name;
  598.   
  599. --- 467,474 ----
  600.       read_mode_group = NULL;
  601.       
  602.       mask = NULL;
  603. !     if (access_mode == 0) access_mode |= ACC_PARSE_VARIABLES;
  604. !     
  605.       if (command == K_GOTO_GROUP)
  606.       goto get_group_name;
  607.   
  608. ***************
  609. *** 792,797 ****
  610. --- 796,802 ----
  611.   
  612.       if (access_group(gh, first, only_unread_articles ?
  613.                gh->last_db_article : gh->current_first - 1,
  614. +              ACC_PARSE_VARIABLES |
  615.                ACC_EXTRA_ARTICLES | ACC_ALSO_CROSS_POSTINGS |
  616.                ACC_ALSO_READ_ARTICLES | ACC_ONLY_READ_ARTICLES,
  617.                (char *)NULL) < 0) {
  618. ***************
  619. *** 905,910 ****
  620. --- 910,917 ----
  621.       if (!seq_cross_filtering)
  622.       if (also_read_articles || mask || also_cross_postings)
  623.           access_mode |= ACC_ALSO_CROSS_POSTINGS;
  624. +     if (seq_cross_filtering && also_unsub_groups)
  625. +     access_mode |= ACC_ALSO_UNSUB_GROUPS;
  626.       if (dont_split_digests)
  627.       access_mode |= ACC_DONT_SPLIT_DIGESTS;
  628.   
  629. ***************
  630. *** 960,966 ****
  631.       }
  632.       merge_memory();
  633.       if (n_articles == 0) return;
  634. !     if (!dont_sort_articles) sort_articles(-1);
  635.   
  636.       dummy_group.group_flag = G_FAKED;
  637.       dummy_group.master_flag = 0;
  638. --- 967,976 ----
  639.       }
  640.       merge_memory();
  641.       if (n_articles == 0) return;
  642. !     if (dont_sort_articles)
  643. !     no_sort_articles();
  644. !     else
  645. !     sort_articles(-1);
  646.   
  647.       dummy_group.group_flag = G_FAKED;
  648.       dummy_group.master_flag = 0;
  649. *** ./LAST/man/nn.1.A    Fri Apr 12 19:29:30 1991
  650. --- man/nn.1.A    Thu Apr 18 18:23:32 1991
  651. ***************
  652. *** 766,771 ****
  653. --- 766,772 ----
  654.   auto-select-closed,
  655.   consolidated-menu,
  656.   counter-delim-left, counter-delim-right,
  657. + counter-padding,
  658.   save-closed-mode.
  659.   .SH THE JUNK-ARTICLES AND LEAVE-NEXT COMMANDS
  660.   The \fBJ\fP {\fBjunk-articles\fP} command is a very flexible command
  661. *** ./LAST/man/nn.1.B    Fri Apr 12 19:28:34 1991
  662. --- man/nn.1.B    Thu Apr 18 18:23:32 1991
  663. ***************
  664. *** 905,916 ****
  665.   \fB:sort\fP [ \fImode\fP ]
  666.   Reorder the articles on the menu according to \fImode\fP or if omitted
  667.   to the default \fBsort-mode\fP.  The following sorting modes are
  668. ! available: \fBarrival\fP (list articles in the order in which they
  669. ! arrived on the system), \fBsubject\fP (articles with identical
  670.   subjects are grouped and ordered after age of the oldest article in
  671. ! the group), lexical (subjects in lexicographical order), \fBage\fP
  672. ! (articles ordered after posting date only), and \fBsender\fP (articles
  673. ! ordered after sender's name).
  674.   .TP
  675.   \fB:toggle\fP \fIvariable\fP
  676.   Toggle a boolean variable.
  677. --- 905,925 ----
  678.   \fB:sort\fP [ \fImode\fP ]
  679.   Reorder the articles on the menu according to \fImode\fP or if omitted
  680.   to the default \fBsort-mode\fP.  The following sorting modes are
  681. ! available:
  682. ! .br
  683. ! \fBarrival\fP: list articles by local article number which
  684. ! will be the same as the order in which they
  685. ! arrived on the system (unless groups are merged),
  686. ! .br
  687. ! \fBsubject\fP: articles with identical
  688.   subjects are grouped and ordered after age of the oldest article in
  689. ! the group,
  690. ! .br
  691. ! \fBlexical\fP: subjects in lexicographical order,
  692. ! .br
  693. ! \fBage\fP: articles ordered after posting date only,
  694. ! .br
  695. ! \fBsender\fP: articles ordered after sender's name.
  696.   .TP
  697.   \fB:toggle\fP \fIvariable\fP
  698.   Toggle a boolean variable.
  699. *** ./LAST/man/nn.1.C    Fri Apr 12 19:29:30 1991
  700. --- man/nn.1.C    Thu Apr 18 18:23:32 1991
  701. ***************
  702. *** 376,381 ****
  703. --- 376,385 ----
  704.   key.  (It will show the symbol <> to indicate that it is awaiting
  705.   confirmation.)
  706.   .TP
  707. + \fBconsolidated-manual\fP    (boolean, default false)
  708. + When set, the \fIonline manual\fP will be presented with one
  709. + menu line for each \fIprogram\fP in the \fInn\fP package.
  710. + .TP
  711.   \fBconsolidated-menu\fP        (boolean, default false)
  712.   When set, \fInn\fP will automatically \fIclose\fP all multi-article
  713.   subjects on entry to a group, so that each subject only occur once on
  714. ***************
  715. *** 389,394 ****
  716. --- 393,406 ----
  717.   The delimiter string output to the right of the article counter in a
  718.   closed subject's menu line.
  719.   .TP
  720. + \fBcounter-padding\fP \fIpad\fP        (integer, default 5)
  721. + On a consolidated menu, the subjects may not be very well aligned
  722. + because the added [...] counters have varying length.  To (partially)
  723. + remedy this, all counters (and subjects without counters) are prefixed
  724. + by up to \fIpad\fP spaces to get better alignment.  Increasing it
  725. + further may yield practially perfect alignment at the cost of less
  726. + space for the subject itself.
  727. + .TP
  728.   \fBcross-filter-seq\fP        (boolean, default true)
  729.   When set, cross posted articles will be presented in the first
  730.   possible group, i.e. according to the current presentation sequence
  731. ***************
  732. *** 618,623 ****
  733. --- 630,643 ----
  734.   Otherwise, the articles in
  735.   a folder will be presented in the sequence in which they were saved.
  736.   .TP
  737. + \fBguard-double-slash\fP    (boolean, default false)
  738. + Normally, when entering a file name, entering two slashes `//' in a
  739. + row (or following a slash by a plus `/+') will cause \fInn\fP to
  740. + erase the entire line and replace it with the `/' (or `+').  On some
  741. + systems, two slashes are used in network file names, and on those
  742. + systems \fBguard-double-slash\fP can be set; that will cause \fInn\fP
  743. + to require \fIthree\fP slashes in a row to clear the input.
  744. + .TP
  745.   \fBheader-lines\fP \fIlist\fP    (string, no default)
  746.   When set, it determines the list of header fields that are shown when
  747.   an article is read instead of the normal one line header showing the
  748. ***************
  749. *** 754,759 ****
  750. --- 774,792 ----
  751.   check for arrival of new mail every minute or so by looking at the
  752.   specified file.
  753.   .TP
  754. + \fBmail-alias-expander\fP \fIprogram\fP    (string, default not set)
  755. + When set, aliases used in mail responses may be expanded by the
  756. + specified \fIprogram\fP.  The program will be given the completed
  757. + response in a file as its only argument, and the aliases should be
  758. + expanded directly in this file (of course the \fIprogram\fP may use
  759. + temporary files and other means to expand the aliases as long the the
  760. + result is stored in the provided file).
  761. + .br
  762. + Notice: currently there are no alias expanders delivered with \fInn\fP.
  763. + .br
  764. + Warning: Errors in the expansion process may lead to the response
  765. + not being sent.
  766. + .TP
  767.   \fBmail-format\fP    (boolean, default false)
  768.   When set, \fInn\fP will save articles in a format that is compatible
  769.   with normal mail folders.
  770. ***************
  771. *** 839,844 ****
  772. --- 872,884 ----
  773.   2: Add a blank line between \fIall\fP articles.
  774.   .fi
  775.   .TP
  776. + \fBmerge-report-rate\fP \fIrate\fP    (integer, default 1)
  777. + When \fInn\fP is invoked with the -m option (directly or via
  778. + \fInngrap\fP), a status report of the merging process is displayed and
  779. + updated on the screen every \fIrate\fP seconds.  The report contains
  780. + the time used so far and an estimate of the time needed to complete
  781. + the merge.
  782. + .TP
  783.   \fBmessage-history\fP \fIN\fP    (integer, default 15)
  784.   Specifies the maximum number, \fIN\fP, of older messages which can be
  785.   recalled with the \fB^P\fP {\fBmessage\fP} command.
  786. ***************
  787. *** 1277,1282 ****
  788. --- 1317,1327 ----
  789.   When set, \fInn\fP will sort articles according to the current
  790.   \fBsort-mode\fP on entry to a group.  Otherwise, articles will be
  791.   presented in order of arrival.
  792. + If not set on entry to a menu for merged groups, the articles from
  793. + each group will be kept together on the menu.  If \fBsort\fP is unset
  794. + while merged groups are presented on the menu, the articles will be
  795. + reordered by local article number (which may not keep articles from
  796. + the same group together).
  797.   .TP
  798.   \fBsort-mode\fP \fImode\fP    (integer, default 1)
  799.   The default sort algorithm used to sort the articles on entry to a
  800. ***************
  801. *** 1283,1289 ****
  802.   news group.  It is a numeric value corresponding to one of the sorting
  803.   methods described in connection with the :sort command:
  804.   .br
  805. !     0 \- arrival (no sorting)
  806.   .br
  807.       1 \- subject (subjects ordered after age of first article)
  808.   .br
  809. --- 1328,1334 ----
  810.   news group.  It is a numeric value corresponding to one of the sorting
  811.   methods described in connection with the :sort command:
  812.   .br
  813. !     0 \- arrival (ordered by article number)
  814.   .br
  815.       1 \- subject (subjects ordered after age of first article)
  816.   .br
  817. *** ./LAST/man/nnpost.1    Mon Jul 16 17:38:49 1990
  818. --- man/nnpost.1    Thu Apr 18 10:49:33 1991
  819. ***************
  820. *** 33,38 ****
  821. --- 33,47 ----
  822.   If a source file is specified with \fB\-f\fP it will be used as the
  823.   initial article body.  If the \fB\-p\fP option is also specified, the
  824.   article is posted directly without editing.
  825. + .LP
  826. + \fInnpost\fP can be used to do unattended postings if sufficient
  827. + arguments are provided on the command line to build the header and the
  828. + body of the article.  The required arguments are: one or more
  829. + newsgroups, a subject (\fB\-s\fP), a source file (\fB\-f\fP), a
  830. + distribution (\fB\-d\fP), and the \fB\-p\fP option.  Other fields
  831. + which are not specified (e.g. keywords) will not be included in the
  832. + header.  The contents of the \fInews-header\fP variable in the
  833. + init file will be included in the header.
  834.   .SH OPTIONS
  835.   .TP
  836.   \fB\-d\fP \fIdistribution\fP
  837. *** ./LAST/master.c    Fri Apr 12 19:28:36 1991
  838. --- master.c    Mon Apr 15 18:56:15 1991
  839. ***************
  840. *** 625,630 ****
  841. --- 625,637 ----
  842.           temp = 0;
  843.       else {
  844.           int mpid;
  845. +         extern char proto_host[];
  846. +         if (proto_host[0]) {
  847. +         printf("Can't kill master on another host (%s)\n", proto_host);
  848. +         log_entry('R', "Attempt to kill master on host %s", proto_host);
  849. +         exit(1);
  850. +         }
  851.   
  852.           for (temp = 10; --temp >= 0; sleep(3)) {
  853.           sleep(3);
  854. *** ./LAST/menu.c    Fri Apr 12 19:29:32 1991
  855. --- menu.c    Tue Apr 16 21:15:25 1991
  856. ***************
  857. *** 37,42 ****
  858. --- 37,43 ----
  859.   export int  menu_spacing = 0;        /* number of screen lines per menu line */
  860.   export char *counter_delim_left  = "[";
  861.   export char *counter_delim_right = "] ";
  862. + export int  counter_padding = 5; /* counters are padded to align subjects */
  863.   
  864.   export int  auto_preview_mode = 0; /* preview rather than select */
  865.   export int  preview_continuation = 12; /* what to do after preview */
  866. ***************
  867. *** 201,212 ****
  868.       save_xy();
  869.   }
  870.   
  871.   static mark()
  872.   {
  873.       register article_header *ah;
  874.       register struct menu_info *mi;
  875.       int lno, lnum, lsubj, lname;
  876. !     int only_counters;
  877.       char cbuf[80];
  878.       attr_type cattr;
  879.   
  880. --- 202,243 ----
  881.       save_xy();
  882.   }
  883.   
  884. + static attr_type closed_attr(mi, cbuf)
  885. + register struct menu_info *mi;
  886. + char *cbuf;
  887. + {
  888. +     char sel[10], unr[10];
  889. +     attr_type cattr;
  890. +     
  891. +     if (mi->mi_unread == 0)
  892. +     cattr = A_READ;
  893. +     else if (mi->mi_total == mi->mi_selected)
  894. +     cattr = A_SELECT;
  895. +     else if (auto_select_closed == 1 && mi->mi_unread == mi->mi_selected)
  896. +     cattr = A_SELECT;
  897. +     else if (mi->mi_selected)
  898. +     cattr = A_KILL;    /* pseudo flag -> highlight cbuf */
  899. +     else
  900. +     cattr = 0;
  901. +     sel[0] = unr[0] = NUL;
  902. +     if (mi->mi_selected && mi->mi_selected < mi->mi_unread)
  903. +     sprintf(sel, "%d/", mi->mi_selected);
  904. +     if (mi->mi_unread && mi->mi_unread < mi->mi_total)
  905. +     sprintf(unr, "%d:", mi->mi_unread);
  906. +     sprintf(cbuf, "%s%s%d", sel, unr, mi->mi_total);
  907. +     return cattr;
  908. + }
  909. + static int subj_indent;
  910.   static mark()
  911.   {
  912.       register article_header *ah;
  913.       register struct menu_info *mi;
  914.       int lno, lnum, lsubj, lname;
  915. !     int pad;
  916.       char cbuf[80];
  917.       attr_type cattr;
  918.   
  919. ***************
  920. *** 219,225 ****
  921.       lno = firstl + ah->menu_line;
  922.       gotoxy(0, lno);
  923.       putchar(ident[mi->mi_art_id]);
  924. !     only_counters = 0;
  925.       goto print_line;
  926.       }
  927.   
  928. --- 250,256 ----
  929.       lno = firstl + ah->menu_line;
  930.       gotoxy(0, lno);
  931.       putchar(ident[mi->mi_art_id]);
  932. !     cattr = closed_attr(mi, cbuf);
  933.       goto print_line;
  934.       }
  935.   
  936. ***************
  937. *** 229,234 ****
  938. --- 260,268 ----
  939.   
  940.       if (ah->flag & A_CLOSED) {
  941.       struct menu_info old;
  942. +     char oldctr[80];
  943. +     attr_type oldattr;
  944.       mi = &menu_info[ah->menu_line];
  945.       old = *mi;
  946.       thread_counters(firsta + cura);
  947. ***************
  948. *** 236,246 ****
  949.           old.mi_selected == mi->mi_selected &&
  950.           old.mi_unread == mi->mi_unread) return;
  951.   
  952. !     if (old.mi_total == old.mi_selected)
  953. !         only_counters = mi->mi_total == mi->mi_selected;
  954. !     else
  955. !         only_counters = mi->mi_total != mi->mi_selected;
  956. !     goto print_line;
  957.       }
  958.   
  959.       if (last_attr == ah->disp_attr) return;
  960. --- 270,281 ----
  961.           old.mi_selected == mi->mi_selected &&
  962.           old.mi_unread == mi->mi_unread) return;
  963.   
  964. !     cattr = closed_attr(mi, cbuf);
  965. !     if (!slow_mode) goto print_line;
  966. !     oldattr = closed_attr(&old, oldctr);
  967. !     if (strcmp(cbuf, oldctr)) goto print_line;
  968. !     last_attr = cattr;
  969.       }
  970.   
  971.       if (last_attr == ah->disp_attr) return;
  972. ***************
  973. *** 270,297 ****
  974.          4    id   subject  (or as 1 if short subject)
  975.        */
  976.   
  977. !     cattr = ah->attr;
  978. !     cbuf[0] = NUL;
  979. !     if (ah->flag & A_CLOSED) {
  980. !     char sel[10], unr[10];
  981. !     if (mi->mi_unread == 0)
  982. !         cattr = A_READ;
  983. !     else if (mi->mi_total == mi->mi_selected)
  984. !         cattr = A_SELECT;
  985. !     else if (auto_select_closed == 1 && mi->mi_unread == mi->mi_selected)
  986. !         cattr = A_SELECT;
  987. !     else if (mi->mi_selected)
  988. !         cattr = A_KILL;    /* pseudo flag -> highlight cbuf */
  989. !     else
  990. !         cattr = 0;
  991. !     sel[0] = unr[0] = NUL;
  992. !     if (mi->mi_selected && mi->mi_selected < mi->mi_unread)
  993. !         sprintf(sel, "%d/", mi->mi_selected);
  994. !     if (mi->mi_unread && mi->mi_unread < mi->mi_total)
  995. !         sprintf(unr, "%d:", mi->mi_unread);
  996. !     sprintf(cbuf, "%s%s%d", sel, unr, mi->mi_total);
  997.       }
  998.   
  999.       if (fmt_linenum > 4) fmt_linenum = 1;
  1000. --- 305,313 ----
  1001.          4    id   subject  (or as 1 if short subject)
  1002.        */
  1003.   
  1004. !     if ((ah->flag & A_CLOSED) == 0) {
  1005. !     cattr = ah->attr;
  1006. !     cbuf[0] = NUL;
  1007.       }
  1008.   
  1009.       if (fmt_linenum > 4) fmt_linenum = 1;
  1010. ***************
  1011. *** 316,323 ****
  1012.        case -1:
  1013.       lsubj -= 9;
  1014.       so_printf("%-8.8s ", ah->sender);
  1015. !     break;
  1016.        case 0:
  1017.       lsubj -= NAME_LENGTH + 1 + 2 + lnum;  /* name. .subj. +.lines */
  1018.       so_printf("%-*s ", NAME_LENGTH, ah->sender);
  1019. --- 332,339 ----
  1020.        case -1:
  1021.       lsubj -= 9;
  1022.       so_printf("%-8.8s ", ah->sender);
  1023. !     goto no_counters;
  1024. !     
  1025.        case 0:
  1026.       lsubj -= NAME_LENGTH + 1 + 2 + lnum;  /* name. .subj. +.lines */
  1027.       so_printf("%-*s ", NAME_LENGTH, ah->sender);
  1028. ***************
  1029. *** 356,364 ****
  1030.       so_printf("%s", cbuf);
  1031.       if (cattr == A_KILL) so_end();
  1032.       so_printf("%s", counter_delim_right);
  1033. !     lsubj -= strlen(cbuf) + strlen(counter_delim_left) + strlen(counter_delim_right);
  1034.       }
  1035. !     
  1036.       if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
  1037.       if (ah->replies == 0 || prt_replies(ah->replies) == 0)
  1038.           so_printf("-");
  1039. --- 372,391 ----
  1040.       so_printf("%s", cbuf);
  1041.       if (cattr == A_KILL) so_end();
  1042.       so_printf("%s", counter_delim_right);
  1043. !     pad = strlen(cbuf) + strlen(counter_delim_left) + strlen(counter_delim_right);
  1044. !     if (cattr == A_KILL) pad += cookie_size * 2;
  1045. !     lsubj -= pad > subj_indent ? pad : subj_indent;
  1046. !     pad = subj_indent - pad;
  1047. !     } else {
  1048. !     lsubj -= subj_indent;
  1049. !     pad = subj_indent;
  1050.       }
  1051. !     if (pad > 0) {
  1052. !     if (pad > 20) pad = 20;
  1053. !     so_printf("                    "+20-pad);
  1054. !     }
  1055. !  no_counters:
  1056.       if (!fmt_rptsubj && lno > firstl && ah->flag & A_SAME) {
  1057.       if (ah->replies == 0 || prt_replies(ah->replies) == 0)
  1058.           so_printf("-");
  1059. ***************
  1060. *** 381,387 ****
  1061.       so_printf(ah->lines >= 0 ? " +%d" : " +?", ah->lines);
  1062.   
  1063.       so_end();
  1064. !     if (ah->flag & A_CLOSED) clrline();
  1065.   
  1066.    out:
  1067.       ah->disp_attr = last_attr;
  1068. --- 408,414 ----
  1069.       so_printf(ah->lines >= 0 ? " +%d" : " +?", ah->lines);
  1070.   
  1071.       so_end();
  1072. !     if (ah->flag & A_CLOSED) clrline_noflush();
  1073.   
  1074.    out:
  1075.       ah->disp_attr = last_attr;
  1076. ***************
  1077. *** 1045,1050 ****
  1078. --- 1072,1079 ----
  1079.       clrpage(firstl + menu_length);
  1080.   
  1081.    draw_menu:
  1082. +     subj_indent = consolidate ? counter_padding : 0;
  1083.       if (!s_keyboard) {
  1084.       int first_menu_line = menu_length;
  1085.   
  1086. ***************
  1087. *** 1136,1145 ****
  1088.   
  1089.     same_prompt:
  1090.   
  1091. !     if (!IS_VISIBLE(articles[firsta+cura]))
  1092. !     cura = next_root_article(firsta + cura) - firsta;
  1093.   
  1094. !      if (cura < 0 || cura > numa) cura = 0;
  1095.   
  1096.        if (numa >= 0) {
  1097.        cursor_at_id();
  1098. --- 1165,1176 ----
  1099.   
  1100.     same_prompt:
  1101.   
  1102. !     if (cura < 0 || cura > numa) cura = 0;
  1103.   
  1104. !     if (!IS_VISIBLE(articles[firsta+cura])) {
  1105. !     cura = next_root_article(firsta + cura) - firsta;
  1106. !     if (cura > numa) cura = 0;
  1107. !     }
  1108.   
  1109.        if (numa >= 0) {
  1110.        cursor_at_id();
  1111. ***************
  1112. *** 1859,1865 ****
  1113.            article_id = tmp;
  1114.        }
  1115.   
  1116. !      repl_attr(article_id, cura, A_KILL, last_attr, 1);
  1117.        goto Prompt;
  1118.   
  1119.         case K_AUTO_SELECT:
  1120. --- 1890,1896 ----
  1121.            article_id = tmp;
  1122.        }
  1123.   
  1124. !      repl_attr(firsta+article_id, firsta+cura+1, A_KILL, last_attr, 1);
  1125.        goto Prompt;
  1126.   
  1127.         case K_AUTO_SELECT:
  1128. *** ./LAST/newsrc.c    Fri Apr 12 19:29:32 1991
  1129. --- newsrc.c    Thu Apr 18 18:16:19 1991
  1130. ***************
  1131. *** 352,357 ****
  1132. --- 352,393 ----
  1133.       }
  1134.   
  1135.       rc = open_file(newsrc_file, OPEN_READ);
  1136. +     if (rc != NULL) {
  1137. +     fseek(rc, (off_t)0, 2);
  1138. +     if (ftell(rc))
  1139. +         rewind(rc);
  1140. +     else {
  1141. +         fclose(rc);
  1142. +         rc = NULL;
  1143. +     }
  1144. +     }
  1145. +     if (rc == NULL) {
  1146. +     sprintf(bak, "%s%s", newsrc_file, bak_suffix ? bak_suffix : ".bak");
  1147. +     if (rc = open_file(bak, OPEN_READ)) {
  1148. +         int ans;
  1149. +         time_t rc_mtime;
  1150. +         
  1151. +         printf("\nThere is no .newsrc file - restore backup? (y) ");
  1152. +         if ((ans = yes(0)) < 0) nn_exit(1);
  1153. +         if (!ans) {
  1154. +         printf("\nConfirm building .newsrc from scratch: (y/n) ");
  1155. +         if ((ans = yes(1)) <= 0) nn_exit(1);
  1156. +         fclose(rc);
  1157. +         rc = NULL;
  1158. +         }
  1159. +         switch (new_group_action) {
  1160. +          case RCX_TIME:
  1161. +          case RCX_TIME_CONF:
  1162. +          case RCX_RNLAST:
  1163. +         last_new_group = get_last_new();
  1164. +         rc_mtime = m_time(rc);
  1165. +         if (last_new_group < 0 || rc_mtime < last_new_group)
  1166. +             last_new_group = rc_mtime;
  1167. +         }
  1168. +     }
  1169. +     }
  1170.       if (rc == NULL) {
  1171.       extern FILE *open_file_search_path();
  1172.   
  1173. ***************
  1174. *** 1365,1373 ****
  1175.       register int i;
  1176.       int header = 1;
  1177.   
  1178. !     re = newobj(regexp *, grep_patterns);
  1179. !     for (i = 0; i < grep_patterns; i++)
  1180. !     re[i] = regcomp(pat[i]);
  1181.   
  1182.       Loop_Groups_Sorted(gh) {
  1183.       if (gh->master_flag & M_IGNORE_GROUP) continue;
  1184. --- 1401,1411 ----
  1185.       register int i;
  1186.       int header = 1;
  1187.   
  1188. !     if (grep_patterns > 0) {
  1189. !     re = newobj(regexp *, grep_patterns);
  1190. !     for (i = 0; i < grep_patterns; i++)
  1191. !         re[i] = regcomp(pat[i]);
  1192. !     }
  1193.   
  1194.       Loop_Groups_Sorted(gh) {
  1195.       if (gh->master_flag & M_IGNORE_GROUP) continue;
  1196. ***************
  1197. *** 1517,1522 ****
  1198. --- 1555,1565 ----
  1199.       if (!silent) printf("%s%s\n", why, gh->group_name);
  1200.       }
  1201.   
  1202. +     if (no_update) {
  1203. +     if (changed) printf("Files were NOT updated\n");
  1204. +     return;
  1205. +     }
  1206.       if (changed) {
  1207.       newsrc_update_freq = 0;
  1208.       dump_newsrc();
  1209. ***************
  1210. *** 1592,1597 ****
  1211. --- 1635,1642 ----
  1212.       total = groups = 0;
  1213.   
  1214.       if (goback_interact) {
  1215. +     if (no_update) printf("Warning: changes will not be saved\n");
  1216. +     init_term(1);
  1217.       raw();
  1218.       }
  1219.   
  1220. ***************
  1221. *** 1632,1637 ****
  1222. --- 1677,1685 ----
  1223.   
  1224.    out:
  1225.   
  1226. +     if (goback_interact)
  1227. +     unset_raw();
  1228.       if (total == 0) {
  1229.       printf("No articles marked\n");
  1230.       return;
  1231. ***************
  1232. *** 1644,1649 ****
  1233. --- 1692,1699 ----
  1234.       printf("%ld article%s marked unread in %d group%s\n",
  1235.              (long)total, plural((long)total),
  1236.              groups, plural((long)groups));
  1237. +     if (no_update) printf("No files were updated\n");
  1238.   }
  1239.   
  1240.   /* fake this for read_active_file */
  1241. *** ./LAST/nn.c    Wed Feb  6 19:14:21 1991
  1242. --- nn.c    Thu Apr 18 18:19:22 1991
  1243. ***************
  1244. *** 612,618 ****
  1245.   
  1246.   static prt_version()
  1247.   {
  1248. !     printf("Release %s,  Kim F. Storm, 1990\n\n", version_id);
  1249.   }
  1250.   
  1251.   display_motd(check)
  1252. --- 612,618 ----
  1253.   
  1254.   static prt_version()
  1255.   {
  1256. !     printf("Release %s,  Kim F. Storm, 1991\n\n", version_id);
  1257.   }
  1258.   
  1259.   display_motd(check)
  1260. ***************
  1261. *** 873,885 ****
  1262.       break;
  1263.   
  1264.        case I_AM_TIDY:
  1265. !     init_term(1);
  1266.       visit_init_file(0, (char *)NULL);
  1267.       group_name_args = opt_nntidy(argc, argv);
  1268.       break;
  1269.   
  1270.        case I_AM_GOBACK:
  1271. !     init_term(1);
  1272.       visit_init_file(0, (char *)NULL);
  1273.       group_name_args = opt_nngoback(argc, &argv);
  1274.       break;
  1275. --- 873,885 ----
  1276.       break;
  1277.   
  1278.        case I_AM_TIDY:
  1279. !     init_term(0);
  1280.       visit_init_file(0, (char *)NULL);
  1281.       group_name_args = opt_nntidy(argc, argv);
  1282.       break;
  1283.   
  1284.        case I_AM_GOBACK:
  1285. !     init_term(0);
  1286.       visit_init_file(0, (char *)NULL);
  1287.       group_name_args = opt_nngoback(argc, &argv);
  1288.       break;
  1289. *** ./LAST/pack_date.c    Wed Feb  6 19:14:21 1991
  1290. --- pack_date.c    Wed Apr 17 08:32:40 1991
  1291. ***************
  1292. *** 17,24 ****
  1293.   
  1294.   /* #define DATE_TEST /* never define this !! */
  1295.   
  1296. - #ifndef USE_OLD_TZ_CODE
  1297.   #undef W
  1298.   #undef E
  1299.   #undef DST
  1300. --- 17,22 ----
  1301. ***************
  1302. *** 192,282 ****
  1303.       }
  1304.       return adjust;
  1305.   }
  1306. - #else
  1307. - static long wtz(h, m, c)
  1308. - int  h, m;
  1309. - char c;
  1310. - {
  1311. -     if (c != 's') h--;        /* daylight savings */
  1312. -     return h*60L+m*30L;
  1313. - }
  1314. - static long etz(h, m, c)
  1315. - int  h, m;
  1316. - char c;
  1317. - {
  1318. -     if (c == 's') h++;        /* summer time */
  1319. -     return -(h*60L+m*30L);
  1320. - }
  1321. - #define TOLOWER(ch) (isupper(ch) ? tolower(ch) : (ch))
  1322. - static long tzone(date)
  1323. - register char *date;
  1324. - {
  1325. -     char ch1, ch2, ch3, ch4;
  1326. -     long tz, wtz(), etz();
  1327. -     while (*date && !isalpha(*date)) date++;
  1328. -     if (*date == NUL || *date == 'G') return 0;
  1329. -     ch1 = TOLOWER(*date);
  1330. -     while (date++, (ch2 = TOLOWER(*date)) == '.')    /* p.s.t. -> pst */
  1331. -     ;
  1332. -     while (date++, (ch3 = TOLOWER(*date)) == '.')
  1333. -     ;
  1334. -     while (date++, (ch4 = TOLOWER(*date)) == '.')
  1335. -     ;
  1336. -     switch (ch1) {
  1337. -      case 'n':
  1338. -     tz = wtz(3,1,0); break;        /* Newfoundland: nst */
  1339. -      case 'a':
  1340. -     if (ch2 == 'e') {
  1341. -         tz = etz(10,0,ch4); break;    /* Australian Eastern: aest, aesst */
  1342. -     }
  1343. -     if (ch2 == 'c') {
  1344. -         tz = etz(9,1,ch4); break;    /* Australian Central: acst, acsst */
  1345. -     }
  1346. -     if (ch2 == 'w') {
  1347. -         tz = etz(8,1,ch4); break;    /* Australian Western: awst, awsst */
  1348. -     }
  1349. -     tz = wtz(4,0,ch2); break;    /* Atlantic: ast, adt */
  1350. -      case 'b':
  1351. -     tz = etz(1,0,0); break;        /* British summer: bst */
  1352. -      case 'c':
  1353. -     tz = wtz(6,0,ch2); break;    /* Central: cst, cdt */
  1354. -      case 'e':
  1355. -     if (ch2 == 'e') {
  1356. -         tz = etz(0,0,ch3); break;    /* European Eastern: eet, eest */
  1357. -     }
  1358. -     tz = wtz(5,0,ch2); break;    /* Eastern: est, edt */
  1359. -      case 'g':
  1360. -     tz = etz(0,0,0); break;        /* Greenwich: gmt */
  1361. -      case 'h':
  1362. -     tz = wtz(10,0,ch2); break;    /* Hawaii: hst, hdt */
  1363. -      case 'j':
  1364. -     tz = etz(9,0,0); break;        /* Japan: jst */
  1365. -      case 'm':
  1366. -     if (ch2 == 'e') {
  1367. -         tz = etz(1,0,ch3); break;    /* Middle European: met, mest */
  1368. -     }
  1369. -     tz = wtz(7,0,ch2); break;    /* Mountain: mst, mdt */
  1370. -      case 'p':
  1371. -     tz = wtz(8,0,ch2); break;    /* Pacific: pst, pdt */
  1372. -      case 'w':
  1373. -     tz = etz(2,0,ch3); break;    /* Western European: wet, west */
  1374. -      case 'y':
  1375. -     tz = wtz(9,0,ch2); break;    /* Yukon: yst, ydt */
  1376. -      default:
  1377. -     tz = 0; break;        /* use GMT if we can't understand it */
  1378. -     }
  1379. -     return tz;
  1380. - }
  1381. - #endif
  1382.   
  1383.   static next_int(dp)
  1384.   char **dp;
  1385. --- 190,195 ----
  1386. *** ./LAST/patchlevel.h    Fri Apr 12 19:29:33 1991
  1387. --- patchlevel.h    Thu Apr 18 10:56:06 1991
  1388. ***************
  1389. *** 26,32 ****
  1390.    *    1991-02-06: Patch #13 (6.4.13) - MEDIUM
  1391.    *    1991-03-22: Patch #14 (6.4.14) - MEDIUM
  1392.    *    1991-04-02: Patch #15 (6.4.15) - LOW
  1393.    */
  1394.   
  1395. ! #define PATCHLEVEL 15
  1396.   
  1397. --- 26,33 ----
  1398.    *    1991-02-06: Patch #13 (6.4.13) - MEDIUM
  1399.    *    1991-03-22: Patch #14 (6.4.14) - MEDIUM
  1400.    *    1991-04-02: Patch #15 (6.4.15) - LOW
  1401. +  *    1991-04-18: Patch #16 (6.4.16) - HIGH
  1402.    */
  1403.   
  1404. ! #define PATCHLEVEL 16
  1405.   
  1406. *** ./LAST/prefix.c    Fri Apr 12 19:28:41 1991
  1407. --- prefix.c    Mon Apr 15 22:28:07 1991
  1408. ***************
  1409. *** 30,37 ****
  1410. --- 30,41 ----
  1411.   #else
  1412.       fprintf(f, "#!%s\n", SHELL);
  1413.   #endif
  1414. + #ifdef PUT_TIMESTAMP_IN_SCRIPTS
  1415.       fprintf(f, "\n# Generated by nn release %s at %s\n\n",
  1416.              version_id, date_time((time_t)0));
  1417. + #else
  1418. +     fprintf(f, "\n# Generated by nn release %s\n\n", version_id);
  1419. + #endif
  1420.       }
  1421.       fprintf(f, "VERSION=\"%s\"\n", version_id);
  1422.   
  1423. *** ./LAST/sequence.c    Fri Oct  5 19:07:18 1990
  1424. --- sequence.c    Tue Apr 16 21:50:25 1991
  1425. ***************
  1426. *** 155,161 ****
  1427.       backp = NULL;
  1428.       seq_ix = 0;
  1429.       Loop_Groups_Sequence(gh) {
  1430. !     gh->preseq_index = (gh->group_flag & G_UNSUBSCRIBED) ? 0 : ++seq_ix;
  1431.       gh->prev_group = backp;
  1432.       backp = gh;
  1433.       }
  1434. --- 155,161 ----
  1435.       backp = NULL;
  1436.       seq_ix = 0;
  1437.       Loop_Groups_Sequence(gh) {
  1438. !     gh->preseq_index = ++seq_ix;
  1439.       gh->prev_group = backp;
  1440.       backp = gh;
  1441.       }
  1442. *** ./LAST/sort.c    Fri Apr 12 19:29:33 1991
  1443. --- sort.c    Mon Apr 15 19:22:09 1991
  1444. ***************
  1445. *** 265,270 ****
  1446. --- 265,288 ----
  1447.       quicksort(articles, n_articles, article_header *, order_date_subj_date);
  1448.   }
  1449.   
  1450. + /*
  1451. +  *    If articles are not sorted via sort_articles, they must still be
  1452. +  *    marked with proper attributes (e.g. A_ROOT_ART) via no_sort_articles.
  1453. +  */
  1454. + no_sort_articles()
  1455. + {
  1456. +     register article_number n;
  1457. +     register article_header *ah;
  1458. +     extern int bypass_consolidation;
  1459. +     for (n = n_articles; --n >= 0;) {
  1460. +     ah = articles[n];
  1461. +     ah->flag &= ~(A_SAME|A_ALMOST_SAME|A_NEXT_SAME|A_ROOT_ART);
  1462. +     ah->flag |= A_ROOT_ART;
  1463. +     }
  1464. +     bypass_consolidation = 1;
  1465. + }
  1466.   
  1467.   /*
  1468.    * Eliminate articles with the A_KILL flag set preserving the present ordering.
  1469. *** ./LAST/term.c    Fri Apr 12 19:28:42 1991
  1470. --- term.c    Thu Apr 18 10:08:19 1991
  1471. ***************
  1472. *** 42,47 ****
  1473. --- 42,48 ----
  1474.   export int  use_visible_bell = 1; /* if supported by terminal */
  1475.   export int  ignore_xon_xoff = 1;
  1476.   export int  multi_key_guard_time = 2; /* tenths of a second */
  1477. + export int  guard_double_slash = 0; /* need /// or //+ to clear line */
  1478.   
  1479.   export key_type help_key = '?';
  1480.   export key_type comp1_key = SP;
  1481. ***************
  1482. *** 353,360 ****
  1483.       return;
  1484.       }
  1485.   
  1486. !     if ((term_name = getenv("TERM")) == NULL)
  1487. !     user_error("No TERM variable in environment");
  1488.   
  1489.       if (!full) return;
  1490.   
  1491. --- 354,365 ----
  1492.       return;
  1493.       }
  1494.   
  1495. !     if ((term_name = getenv("TERM")) == NULL) {
  1496. !     if (full)
  1497. !         user_error("No TERM variable in environment");
  1498. !     else
  1499. !         term_name = "unknown";
  1500. !     }
  1501.   
  1502.       if (!full) return;
  1503.   
  1504. ***************
  1505. *** 556,561 ****
  1506. --- 561,573 ----
  1507.       fl;
  1508.   }
  1509.   
  1510. + clrline_noflush()
  1511. + {
  1512. +     BATCH_CHECK;
  1513. +     putp(clr_eol);
  1514. + }
  1515.   clrpage(lineno)
  1516.   register int lineno;
  1517.   {
  1518. ***************
  1519. *** 1255,1265 ****
  1520.       if (i == max) continue;
  1521.   
  1522.       if (i > 0 && buf[i-1] == '/' && (c == '/' || c == '+')) {
  1523. !       extern int file_completion();
  1524. !       if (completion == file_completion) {
  1525. !         while (i > 0) { putchar(BS); i--; }
  1526. !         clrline();
  1527. !       }
  1528.       }
  1529.   
  1530.       putchar(c);
  1531. --- 1267,1280 ----
  1532.       if (i == max) continue;
  1533.   
  1534.       if (i > 0 && buf[i-1] == '/' && (c == '/' || c == '+')) {
  1535. !         if (c != '/' || !guard_double_slash || (i > 1 && buf[i-2] == '/')) {
  1536. !         extern int file_completion();
  1537. !         if (completion == file_completion) {
  1538. !             while (i > 0) { putchar(BS); i--; }
  1539. !             clrline();
  1540. !         }
  1541. !         }
  1542.       }
  1543.   
  1544.       putchar(c);
  1545. ***************
  1546. *** 1569,1576 ****
  1547.       msg_ptr = msg_stack;
  1548.       }
  1549.   
  1550. !     BATCH_CHECK;
  1551.       gotoxy(0, Lines-1);
  1552.       fputs(errmsg, stdout);
  1553.       clrline();
  1554. --- 1584,1595 ----
  1555.       msg_ptr = msg_stack;
  1556.       }
  1557.   
  1558. !     if (terminal_speed == 0) {
  1559. !     printf("%s\n", errmsg);
  1560. !     fl;
  1561. !     return;
  1562. !     }
  1563. !     
  1564.       gotoxy(0, Lines-1);
  1565.       fputs(errmsg, stdout);
  1566.       clrline();
  1567. *** ./LAST/variable.c    Fri Apr 12 19:29:34 1991
  1568. --- variable.c    Tue Apr 16 23:21:00 1991
  1569. ***************
  1570. *** 80,85 ****
  1571. --- 80,86 ----
  1572.       included_mark[],
  1573.       *inews_program,
  1574.       *initial_newsrc_path,
  1575. +     *mail_alias_expander,
  1576.       *mail_box,
  1577.       *mail_record,
  1578.       *mail_script,
  1579. ***************
  1580. *** 122,128 ****
  1581. --- 123,131 ----
  1582.       conf_dont_sleep,
  1583.       conf_group_entry,
  1584.       conf_junk_seen,
  1585. +     consolidated_manual,
  1586.       consolidated_menu,
  1587. +     counter_padding,
  1588.       delay_redraw,
  1589.       dflt_kill_select,
  1590.       do_kill_handling,
  1591. ***************
  1592. *** 140,145 ****
  1593. --- 143,149 ----
  1594.       fmt_rptsubj,
  1595.       folder_format_check,
  1596.       folder_rewrite_trace,
  1597. +     guard_double_slash,
  1598.       ignore_xon_xoff,
  1599.       include_art_id,
  1600.       include_full_header,
  1601. ***************
  1602. *** 210,215 ****
  1603. --- 214,220 ----
  1604.       mark_read_return,
  1605.       mark_read_skip,
  1606.       menu_spacing,
  1607. +     merge_report_rate,
  1608.       message_history,
  1609.       min_pv_window,
  1610.       multi_key_guard_time,
  1611. ***************
  1612. *** 319,327 ****
  1613. --- 324,334 ----
  1614.       "confirm-entry-limit",    INT 0,        (char **)&conf_entry_limit,
  1615.       "confirm-junk-seen",     BOOL 0,        (char **)&conf_junk_seen,
  1616.       "confirm-messages",        BOOL 0,        (char **)&conf_dont_sleep,
  1617. +     "consolidated-manual",    BOOL 0,        (char **)&consolidated_manual,
  1618.       "consolidated-menu",    BOOL 1,        (char **)&consolidated_menu,
  1619.       "counter-delim-left",    STR 5,        (char **)&counter_delim_left,
  1620.       "counter-delim-right",    STR 5,        (char **)&counter_delim_right,
  1621. +     "counter-padding",        INT 1,        (char **)&counter_padding,
  1622.       "cross-filter-seq",        BOOL 0,        (char **)&seq_cross_filtering,
  1623.       "cross-post",        BOOL 0,        (char **)&also_cross_postings,
  1624.       "data-bits",        INT 0,        (char **)&data_bits,
  1625. ***************
  1626. *** 353,358 ****
  1627. --- 360,366 ----
  1628.       "follow-distribution",    STR 0,        (char **)&distribution_follow,
  1629.       "from-line-parsing",    INT 0,        (char **)&strict_from_parse,
  1630.       "fsort",            BOOL 2,        (char **)&dont_sort_folders,
  1631. +     "guard-double-slash",    BOOL 0,        (char **)&guard_double_slash,
  1632.       "header-lines",        STR 0,        (char **)&header_lines,
  1633.       "help-key",            KEY 0,        (char **)&help_key,
  1634.       "ignore-xon-xoff",        BOOL 0,        (char **)&ignore_xon_xoff,
  1635. ***************
  1636. *** 375,380 ****
  1637. --- 383,389 ----
  1638.       "long-menu",        BOOL 1,        (char **)&long_menu,
  1639.       "macro-debug",        BOOL 0,        (char **)¯o_debug,
  1640.       "mail",            STR 2,        (char **)&mail_box,
  1641. +     "mail-alias-expander",    STR 0,        (char **)&mail_alias_expander,
  1642.       "mail-format",        BOOL 0,        (char **)&use_mail_folders,
  1643.       "mail-header",        STR 0,        (char **)&extra_mail_headers,
  1644.       "mail-record",        STR 2,        (char **)&mail_record,
  1645. ***************
  1646. *** 387,392 ****
  1647. --- 396,402 ----
  1648.       "marked-by-read-return",    INT 0,        (char **)&mark_read_return,
  1649.       "marked-by-read-skip",    INT 0,        (char **)&mark_read_skip,
  1650.       "menu-spacing",        INT 1,        (char **)&menu_spacing,
  1651. +     "merge-report-rate",    INT 0,        (char **)&merge_report_rate,
  1652.       "message-history",        INT 0,        (char **)&message_history,
  1653.       "min-window",        INT 1,        (char **)&min_pv_window,
  1654.       "mmdf-format",        BOOL 0,        (char **)&use_mmdf_folders,
  1655. ***************
  1656. *** 661,672 ****
  1657.           return 1;
  1658.   
  1659.        case 2:
  1660. !         if (BOOL_VAR == on) {
  1661. !         BOOL_VAR = !on;
  1662. !         if (!in_init) {
  1663. !             sort_articles(BOOL_VAR ? 0 : -1);
  1664. !             return 1;
  1665. !         }
  1666.           }
  1667.           break;
  1668.   
  1669. --- 671,685 ----
  1670.           return 1;
  1671.   
  1672.        case 2:
  1673. !         if (BOOL_VAR) {    /* don't change if already ok */
  1674. !         if (!on) break;
  1675. !         } else
  1676. !         if (on) break;
  1677. !         BOOL_VAR = !on;
  1678. !         if (!in_init) {
  1679. !         sort_articles(BOOL_VAR ? 0 : -1);
  1680. !         return 1;
  1681.           }
  1682.           break;
  1683.   
  1684.